package edu.westga.sketchit2009cs.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.prefs.Preferences;

import javax.swing.BoxLayout;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;

/**
 * Sketchit2009csMainFrame defines the main window size and is the base from
 * which every other class will draw the components for the Sketchit2009cs game.
 * 
 * @author Steven Campbell, RJ Hill, Daniel Reeves, Fall 2009
 * 
 */

public class Sketchit2009csMainFrame implements Runnable {

	private static final long serialVersionUID = 1L;
	public static JFrame mainWindow;
	public static JPanel theContentPanel;
	public JMenuBar mainMenuBar;
	public JMenu fileMenu;
	public JMenu selectInterfaceMenu;
	public JMenu helpMenu;
	public File theHelpFile;
	public JFrame helpFrame;
	public JPanel helpPanel;
	public JEditorPane theHelpPane;
	public Preferences prefs;
	private static final int WINDOW_OFFSET = 600;
	public final String GAME_TITLE_STRING_VALUE = "SketchIt2009cs";
	public final String FILE_MENU_STRING_VALUE = "File";
	public final String MAIN_MENU_STRING_VALUE = "Main Menu";
	public final String CTRL_M_STRING_VALUE = "ctrl M";
	public final String QUIT_MENU_ITEM_STRING_VALUE = "Quit";
	public final String CTRL_Q_STRING_VALUE = "ctrl Q";
	public final String PLAY_GAME_STRING_VALUE = "Play Game!";
	public final String JOIN_EXISTING_GAME_STRING_VALUE = "Join Existing Game";
	public final String CTRL_E_STRING_VALUE = "ctrl E";
	public final String HOST_A_NEW_GAME_STRING_VALUE = "Host A New Game";
	public final String CTRL_N_STRING_VALUE = "ctrl N";
	public final String HELP_STRING_VALUE = "Help";
	public final String HOW_TO_USE_PROGRAM_STRING_VALUE = "How to use this program";
	public final String CTRL_H_STRING_VALUE = "ctrl H";
	public final String ABOUT_STRING_VALUE = "About";
	public final String CTRL_A_STRING_VALUE = "ctrl A";
	public final String WANT_TO_QUIT_QUESTION_STRING_VALUE = "Do you really want to quit?\n";
	public final String QUIT_GAME_STRING_VALUE = "Quit Game";
	public final String HELP_FILE_STRING_VALUE = "help.txt";
	public final String ABOUT_DIALOG_TITLE_STRING_VALUE = "About Sketchit2009cs";
	public final String ABOUT_DIALOG_STRING_VALUE = "Authors:\n    Steven Campbell\n    RJ Hill\n    Daniel Reeves\n\n"
			+ "This program was created by Computer Science Majors at\n"
			+ "The University of West Georgia.";
	public final static String FORWARD_SLASH_STRING_VALUE = "/";
	public final String HELP_HTML_STRING_VALUE = "http://stu.westga.edu/~dreeves1/help.html";
	public final String HELP_WINDOW_STRING_VALUE = "Help Window";
	public final String ERROR_DISPLAY_STRING_VALUE ="Error displaying ";
	public static String playerName;
	public static String hostIpAddress;
    public static int hostAndJoinPortNumber;
    public static boolean isHost = false;
    

	/**
	 * 
	 * The Sketchit2009csMainFrame Constructor which builds the and sets up the
	 * main window.
	 * 
	 * @throws Exception
	 *             Host class can throw an exception when pulling the IP address
	 */
	public Sketchit2009csMainFrame() throws Exception {
		setUpMainWindow();
		mainWindow.setContentPane(Sketchit2009csMainFrame.theContentPanel);
		theContentPanel.validate();
		mainWindow.setResizable(false);
		buildMainMenuBar();
	}

	// setup up the main window components.
	private void setUpMainWindow() throws Exception {
		Sketchit2009csMainFrame.mainWindow = new JFrame(GAME_TITLE_STRING_VALUE);
		Sketchit2009csMainFrame.mainWindow
				.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		
		// ***********************************************************************
		// Comment the following line out for major/repeated edit 
		// instances where the main window is constantly opened/closed.
		// Note that the above code JFrame.DO_NOTHING_ON_CLOSE will NOT
		// close the program, change to JFrame.EXIT_ON_CLOSE to properly
		// shut down the program.
		userConfirmsExitOnClose();
		// ***********************************************************************
		
		Sketchit2009csMainFrame.mainWindow.setPreferredSize(new Dimension(
				WINDOW_OFFSET + 200, WINDOW_OFFSET ));
		Sketchit2009csMainFrame.theContentPanel = new JPanel();
		Sketchit2009csMainFrame.theContentPanel.setBackground(Color.LIGHT_GRAY);
		Sketchit2009csMainFrame.theContentPanel.setLayout(new BoxLayout(
				Sketchit2009csMainFrame.theContentPanel, BoxLayout.Y_AXIS));
		Sketchit2009csMainFrame.theContentPanel
				.add(new Sketchit2009csDisplay());
	}

	// Makes the Main window visible.
	public void show() {
		Sketchit2009csMainFrame.mainWindow.pack();
		Sketchit2009csMainFrame.mainWindow.setLocationRelativeTo(null);
		Sketchit2009csMainFrame.mainWindow.setVisible(true);
	}

	// Creates a menu bar and adds menus to it.
	private void buildMainMenuBar() {
		this.mainMenuBar = new JMenuBar();
		Sketchit2009csMainFrame.mainWindow.setJMenuBar(this.mainMenuBar);

		this.buildFileMenu();
		this.mainMenuBar.add(fileMenu);
		this.buildInterfaceMenu();
		this.mainMenuBar.add(selectInterfaceMenu);
		this.buildHelpMenu();
		this.mainMenuBar.add(helpMenu);
	}

	// Creates the file menu and adds menu items to it.
	private void buildFileMenu() {
		fileMenu = new JMenu(FILE_MENU_STRING_VALUE);
		fileMenu.setMnemonic(KeyEvent.VK_F);

		addMainMenuItem();
		addQuitMenuItem();
	}

	// Sets up the menu item to go back to the main menu
	private void addMainMenuItem() {
		JMenuItem quitItem = new JMenuItem(MAIN_MENU_STRING_VALUE);
		quitItem.setAccelerator(KeyStroke.getKeyStroke(CTRL_M_STRING_VALUE));
		quitItem.setMnemonic(KeyEvent.VK_M);
		quitItem.addActionListener(new MainMenuListener());
		fileMenu.add(quitItem);
	}

	// Sets up the menu item to exit the program.
	private void addQuitMenuItem() {
		JMenuItem quitItem = new JMenuItem(QUIT_MENU_ITEM_STRING_VALUE);
		quitItem.setAccelerator(KeyStroke.getKeyStroke(CTRL_Q_STRING_VALUE));
		quitItem.setMnemonic(KeyEvent.VK_Q);
		quitItem.addActionListener(new QuitListener());
		fileMenu.add(quitItem);
	}

	// Create the interface menu and add selection items to it
	private void buildInterfaceMenu() {
		selectInterfaceMenu = new JMenu(PLAY_GAME_STRING_VALUE);
		selectInterfaceMenu.setMnemonic(KeyEvent.VK_I);

		addExistingGameMenuItem();
		addHostNewGameMenuItem();
	}

	// Sets up menu to select the 'existing game' interface
	private void addExistingGameMenuItem() {
		JMenuItem existingGameInterfaceItem = new JMenuItem(
				JOIN_EXISTING_GAME_STRING_VALUE);
		existingGameInterfaceItem.setAccelerator(KeyStroke
				.getKeyStroke(CTRL_E_STRING_VALUE));
		existingGameInterfaceItem.setMnemonic(KeyEvent.VK_E);
		existingGameInterfaceItem
				.addActionListener(new SelectExistingGameMenuButtonListener());
		selectInterfaceMenu.add(existingGameInterfaceItem);
	}

	// Sets up menu to select the 'host a new game' interface
	private void addHostNewGameMenuItem() {
		JMenuItem newGameInterfaceItem = new JMenuItem(
				HOST_A_NEW_GAME_STRING_VALUE);
		newGameInterfaceItem.setAccelerator(KeyStroke
				.getKeyStroke(CTRL_N_STRING_VALUE));
		newGameInterfaceItem.setMnemonic(KeyEvent.VK_N);
		newGameInterfaceItem
				.addActionListener(new SelectNewGameMenuButtonListener());
		selectInterfaceMenu.add(newGameInterfaceItem);
	}

	// Sets up help menu
	private void buildHelpMenu() {
		helpMenu = new JMenu(HELP_STRING_VALUE);
		helpMenu.setMnemonic(KeyEvent.VK_H);

		addHelpGameMenuItem();
		addAboutMenuItem();
	}

	// Sets up help about the game
	private void addHelpGameMenuItem() {
		JMenuItem newHelpInterfaceItem = new JMenuItem(
				HOW_TO_USE_PROGRAM_STRING_VALUE);
		newHelpInterfaceItem.setAccelerator(KeyStroke
				.getKeyStroke(CTRL_H_STRING_VALUE));
		newHelpInterfaceItem.setMnemonic(KeyEvent.VK_H);
		newHelpInterfaceItem.addActionListener(new SelectHelpMenuListener());
		helpMenu.add(newHelpInterfaceItem);
	}

	// Sets up the 'about' page for the game
	private void addAboutMenuItem() {
		JMenuItem newAboutInterfaceItem = new JMenuItem(ABOUT_STRING_VALUE);
		newAboutInterfaceItem.setAccelerator(KeyStroke
				.getKeyStroke(CTRL_A_STRING_VALUE));
		newAboutInterfaceItem.setMnemonic(KeyEvent.VK_A);
		newAboutInterfaceItem.addActionListener(new SelectAboutMenuListener());
		helpMenu.add(newAboutInterfaceItem);
	}

	// Sets up the display
	public static void addSplashScreen() throws Exception {
		theContentPanel.removeAll();
		theContentPanel.add(new Sketchit2009csDisplay());
		theContentPanel.validate();
		mainWindow.repaint();
	}
	
	//Get the host IP address
	public static String[] getHostIpAddress() throws UnknownHostException {
		InetAddress Address = InetAddress.getLocalHost();
		String[] iPAddress = Address.toString().split(
				FORWARD_SLASH_STRING_VALUE);
		return iPAddress;
	}
	
	// If the user presses the X Button on the right hand side of the screen, then the program asks
	// the user if they want to quit.
	private void userConfirmsExitOnClose() {
		Sketchit2009csMainFrame.mainWindow.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e) {
				JOptionPane quitDialog = new JOptionPane();
				int response = JOptionPane.showConfirmDialog(quitDialog,
						WANT_TO_QUIT_QUESTION_STRING_VALUE, QUIT_GAME_STRING_VALUE,
						JOptionPane.YES_NO_OPTION);
				
				if (response == JOptionPane.YES_OPTION) {
					System.exit(0);
				}
				else if(response == JOptionPane.NO_OPTION){
					return;
				}
			}
		});
	}

	// ***************************************************************
	// ***************** Inner listener classes **********************
	// ***************************************************************

	// Action listener for components that end the program.
	private class QuitListener implements ActionListener {

		/*
		 * Terminates the program. User must confirm. A dialog box pops up.
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			JOptionPane quitDialog = new JOptionPane();  
			int response = JOptionPane.showConfirmDialog(quitDialog, WANT_TO_QUIT_QUESTION_STRING_VALUE,
					QUIT_GAME_STRING_VALUE, JOptionPane.YES_NO_OPTION); 
			if (response == JOptionPane.YES_OPTION) {
				System.exit(0);
			} else if (response == JOptionPane.NO_OPTION) {
				return;
			}
		}
	}

	// Action listener for components that returns the user to the main menu
	public class MainMenuListener implements ActionListener {

		/*
		 * Returns user to main menu
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			theContentPanel.removeAll();
			theContentPanel.validate();
			mainWindow.repaint();
			theContentPanel.setBackground(Color.LIGHT_GRAY);
			theContentPanel.setLayout(new BoxLayout(theContentPanel,
					BoxLayout.Y_AXIS));
			try {
				addSplashScreen();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
		}
	}
	
	/**
	 * Resets the main window to the splash screen
	 */
	public static void ResetMainWindow(){
		
		theContentPanel.removeAll();
		theContentPanel.validate();
		mainWindow.repaint();
		theContentPanel.setBackground(Color.LIGHT_GRAY);
		theContentPanel.setLayout(new BoxLayout(theContentPanel,
				BoxLayout.Y_AXIS));
		try {
			addSplashScreen();
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		
	}

	// Action listener for the how to use this program menu item in the help
	// menu.
	private class SelectHelpMenuListener implements ActionListener {

		/*
		 * Runs the help dialog window
		 */
		@Override
		public void actionPerformed(ActionEvent arg0) {
			
    		helpFrame = new JFrame(HELP_WINDOW_STRING_VALUE);
    		helpFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    		helpFrame.setPreferredSize(new Dimension(400, 500));
    		helpFrame.pack();
    		helpFrame.setLocationRelativeTo(null);
    		helpFrame.setVisible(true);
			helpPanel = new JPanel();
		    helpPanel.setLayout(new BorderLayout());
		    helpFrame.add(helpPanel, BorderLayout.CENTER);
		    
		    String url = HELP_HTML_STRING_VALUE;
		    try {
		      JEditorPane htmlPane = new JEditorPane(url);
		      htmlPane.setEditable(false);
		      helpPanel.add(new JScrollPane(htmlPane));
		    } catch(IOException ioe) {
		      System.err.println(ERROR_DISPLAY_STRING_VALUE + url);
		    }
		}
	}

	// Action listener for the about menu item in the help menu
	private class SelectAboutMenuListener implements ActionListener {

		/*
		 * runs the About dialog box.
		 */
		@Override
		public void actionPerformed(ActionEvent arg0) {
			JDialog aboutDialog = new JDialog();
			JOptionPane.showMessageDialog(aboutDialog,
					ABOUT_DIALOG_STRING_VALUE, ABOUT_DIALOG_TITLE_STRING_VALUE,
					1);
		}
	}

	/*
	 * Action listener for components that change the content panel to show the
	 * join an existing game panel.
	 */

	public static class SelectExistingGameMenuButtonListener implements
			ActionListener {

		/*
		 * Clears the content panel, and redraws the window and adds the
		 * JoinPanel to the MainFrame.
		 */
		@Override
		public void actionPerformed(ActionEvent arg0) {
			theContentPanel.removeAll();
			try {
				theContentPanel.add(new JoinPanel());
			} catch (Exception e) {
				e.printStackTrace();
			}
			theContentPanel.validate();
			mainWindow.repaint();
			isHost = false;
		}
	}

	/*
	 * Action listener for components that change the content panel to show the
	 * host a new game panel.
	 */

	public static class SelectNewGameMenuButtonListener implements
			ActionListener {

		/*
		 * Clears the content panel and redraws the window and adds the
		 * HostPanel to the Sketchit2009csMainFrame.
		 */
		@Override
		public void actionPerformed(ActionEvent arg0) {
			theContentPanel.removeAll();
			try {
				theContentPanel.add(new HostPanel());
			} catch (Exception e) {
				e.printStackTrace();
			}
			theContentPanel.validate();
			mainWindow.repaint();
			isHost = true;
		}
	}

	// Action listener for components which return to the main menu
	public static class CancelButtonListener implements ActionListener {

		/*
		 * Clears current items on the Sketchit2009csMainFrame and Returns user
		 * to main menu.
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			theContentPanel.removeAll();
			theContentPanel.validate();
			mainWindow.repaint();
			theContentPanel.setBackground(Color.LIGHT_GRAY);
			theContentPanel.setLayout(new BoxLayout(theContentPanel,
					BoxLayout.Y_AXIS));
			try {
				cancelButtonHostAndJoinPanels();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
		}

		// method to add the Sketchit2009csDisplay to the
		// Skecthit2009csMainFrame.
		private void cancelButtonHostAndJoinPanels() throws Exception {
			theContentPanel.removeAll();
			theContentPanel.add(new Sketchit2009csDisplay());
			theContentPanel.validate();
			mainWindow.repaint();
		}
	}

	@Override
	public void run() {
		this.show();		
	}

}
